
package com.nervytech.tutorcruise.spring.controller;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.ow2.chameleon.tinyurl.TinyURLShortener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.nervytech.tutorcruise.application.util.ApplicationDateUtil;
import com.nervytech.tutorcruise.course.beans.CourseDetailsBean;
import com.nervytech.tutorcruise.course.beans.CourseSearchResultBean;
import com.nervytech.tutorcruise.course.beans.CourseSearchResultPageBean;
import com.nervytech.tutorcruise.db.dao.model.CourseMaster;
import com.nervytech.tutorcruise.db.dao.model.CourseRequests;
import com.nervytech.tutorcruise.db.dao.model.CourseRequestsLocation;
import com.nervytech.tutorcruise.db.dao.model.CourseSchedule;
import com.nervytech.tutorcruise.db.service.interfaces.ICategoryService;
import com.nervytech.tutorcruise.db.service.interfaces.ICountryService;
import com.nervytech.tutorcruise.db.service.interfaces.ICourseLocationService;
import com.nervytech.tutorcruise.db.service.interfaces.ICourseMasterService;
import com.nervytech.tutorcruise.db.service.interfaces.ICourseRequestsLocationService;
import com.nervytech.tutorcruise.db.service.interfaces.ICourseRequestsService;
import com.nervytech.tutorcruise.db.service.interfaces.ICourseScheduleService;
import com.nervytech.tutorcruise.db.service.interfaces.ICurrencyService;
import com.nervytech.tutorcruise.db.service.interfaces.IStateService;
import com.nervytech.tutorcruise.db.service.interfaces.ITimezoneService;
import com.nervytech.tutorcruise.service.exception.TrainerCruiseServiceException;
import com.nervytech.tutorcruise.spring.course.form.CourseRequestForm;
import com.nervytech.tutorcruise.spring.course.form.CreateCourseAgendaForm;
import com.nervytech.tutorcruise.spring.course.form.CreateCourseOverviewForm;
import com.nervytech.tutorcruise.spring.course.form.CreateCourseScheduleForm;
import com.nervytech.tutorcruise.spring.course.form.CreateCourseSocialForm;
import com.nervytech.tutorcruise.spring.form.validator.CourseOverviewValidator;
import com.nervytech.tutorcruise.spring.form.validator.CourseRequestValidator;
import com.nervytech.tutorcruise.spring.form.validator.CourseScheduleValidator;
import com.nervytech.tutorcruise.spring.security.auth.SessionUser;
import com.nervytech.tutorcruise.spring.security.auth.UserDetailsServiceImpl;

@Controller
@RequestMapping({ "/pub/course", "/usr/course" })
public class CourseController {

	@Autowired
	private CourseOverviewValidator courseOverviewValidator;

	@Autowired
	private CourseScheduleValidator courseScheduleValidator;

	@Autowired
	private CourseRequestValidator courseRequestValidator;

	@Autowired
	private ICourseRequestsService courseRequestService;

	@Autowired
	private ICourseRequestsLocationService courseReqLocService;

	@Autowired
	private ICourseLocationService courseLocService;

	@Autowired
	private ICourseMasterService courseMasterService;

	@Autowired
	private ICourseScheduleService courseScheduleService;

	@Autowired
	private ICategoryService catService;

	@Autowired
	private ICountryService countryService;

	@Autowired
	private ITimezoneService timezoneService;

	@Autowired
	private ICurrencyService currencyService;

	@Autowired
	private IStateService stateService;

	private Map<Integer, String> categoryMap;
	private Map<Integer, String> currenciesMap;
	private Map<Integer, String> locationsMap;
	private Map<Integer, String> timeZonesMap;
	private Map<Integer, String> countryMap;
	private Map<Integer, String> statesMap;

	@ModelAttribute("categoryMap")
	public Map<Integer, String> populateCategoryMap() {
		if (categoryMap == null) {
			SessionUser userDetails = UserDetailsServiceImpl
					.currentUserDetails();
			long userId = userDetails.getUserId();
			categoryMap = new LinkedHashMap<Integer, String>();
			categoryMap.put(Integer.valueOf(-1), "Select Category");
			Map catsMap;
			try {
				catsMap = catService.getCategoryMap();
			} catch (TrainerCruiseServiceException e) {
				e.printStackTrace();
				catsMap = new LinkedHashMap<Integer, String>();
			}
			int catId;
			String catName;
			for (Iterator iterator = catsMap.entrySet().iterator(); iterator
					.hasNext(); categoryMap
					.put(Integer.valueOf(catId), catName)) {
				java.util.Map.Entry entry = (java.util.Map.Entry) iterator
						.next();
				catId = ((Integer) entry.getKey()).intValue();
				catName = (String) entry.getValue();
			}

		}
		return categoryMap;
	}

	@ModelAttribute("currenciesMap")
	public Map<Integer, String> populateCurrenciesMap() {
		if (currenciesMap == null) {
			SessionUser userDetails = UserDetailsServiceImpl
					.currentUserDetails();
			long userId = userDetails.getUserId();
			currenciesMap = new LinkedHashMap<Integer, String>();
			currenciesMap.put(Integer.valueOf(-1), "Select Currency");
			Map currMap;
			try {
				currMap = currencyService.getCurrenciesMap();
			} catch (TrainerCruiseServiceException e) {
				e.printStackTrace();
				currMap = new LinkedHashMap<Integer, String>();
			}
			int catId;
			String catName;
			for (Iterator iterator = currMap.entrySet().iterator(); iterator
					.hasNext(); currenciesMap.put(Integer.valueOf(catId),
					catName)) {
				java.util.Map.Entry entry = (java.util.Map.Entry) iterator
						.next();
				catId = ((Integer) entry.getKey()).intValue();
				catName = (String) entry.getValue();
			}

		}
		return currenciesMap;
	}

	@ModelAttribute("timeZonesMap")
	public Map<Integer, String> populateTimezonesMap() {
		if (timeZonesMap == null) {
			SessionUser userDetails = UserDetailsServiceImpl
					.currentUserDetails();
			long userId = userDetails.getUserId();
			timeZonesMap = new LinkedHashMap<Integer, String>();
			timeZonesMap.put(Integer.valueOf(-1), "Select Timezone");
			Map currMap;
			try {
				currMap = timezoneService.getTimezonesMap();
			} catch (TrainerCruiseServiceException e) {
				e.printStackTrace();
				currMap = new LinkedHashMap<Integer, String>();
			}
			int catId;
			String catName;
			for (Iterator iterator = currMap.entrySet().iterator(); iterator
					.hasNext(); timeZonesMap.put(Integer.valueOf(catId),
					catName)) {
				java.util.Map.Entry entry = (java.util.Map.Entry) iterator
						.next();
				catId = ((Integer) entry.getKey()).intValue();
				catName = (String) entry.getValue();
			}

		}
		return timeZonesMap;
	}

	@ModelAttribute("locationsMap")
	public Map<Integer, String> populateLocationsMap() {
		if (locationsMap == null) {
			SessionUser userDetails = UserDetailsServiceImpl
					.currentUserDetails();
			long userId = userDetails.getUserId();
			locationsMap = new LinkedHashMap<Integer, String>();
			locationsMap.put(Integer.valueOf(-1), "Select Location");
			Map catsMap;
			try {
				catsMap = courseLocService.getLocationsMap(userId);
			} catch (TrainerCruiseServiceException e) {
				e.printStackTrace();
				catsMap = new LinkedHashMap<Integer, String>();
			}
			int catId;
			String catName;
			for (Iterator iterator = catsMap.entrySet().iterator(); iterator
					.hasNext(); locationsMap.put(Integer.valueOf(catId),
					catName)) {
				java.util.Map.Entry entry = (java.util.Map.Entry) iterator
						.next();
				catId = ((Integer) entry.getKey()).intValue();
				catName = (String) entry.getValue();
			}

		}
		return locationsMap;
	}

	@ModelAttribute("countryMap")
	public Map<Integer, String> populateCountryMap() {
		if (countryMap == null) {
			SessionUser userDetails = UserDetailsServiceImpl
					.currentUserDetails();
			long userId = userDetails.getUserId();
			countryMap = new LinkedHashMap<Integer, String>();
			countryMap.put(Integer.valueOf(-1), "Select Category");
			Map catsMap;
			try {
				catsMap = countryService.getCountryMap();
			} catch (TrainerCruiseServiceException e) {
				e.printStackTrace();
				catsMap = new LinkedHashMap<Integer, String>();
			}
			int catId;
			String catName;
			for (Iterator iterator = catsMap.entrySet().iterator(); iterator
					.hasNext(); countryMap.put(Integer.valueOf(catId), catName)) {
				java.util.Map.Entry entry = (java.util.Map.Entry) iterator
						.next();
				catId = ((Integer) entry.getKey()).intValue();
				catName = (String) entry.getValue();
			}

		}
		return countryMap;
	}

	@ModelAttribute("statesMap")
	public Map<Integer, String> populateStatesMap() {
		if (statesMap == null) {
			SessionUser userDetails = UserDetailsServiceImpl
					.currentUserDetails();
			long userId = userDetails.getUserId();
			statesMap = new LinkedHashMap<Integer, String>();
			statesMap.put(Integer.valueOf(-1), "Select States");
			Map stMap;
			try {
				stMap = stateService.getStatesMap(101);
			} catch (TrainerCruiseServiceException e) {
				e.printStackTrace();
				stMap = new LinkedHashMap<Integer, String>();
			}
			System.out
					.println((new StringBuilder("statesMapPPPPPPPPPPPPPPPP "))
							.append(stMap).toString());
			int catId;
			String catName;
			for (Iterator iterator = stMap.entrySet().iterator(); iterator
					.hasNext(); statesMap.put(Integer.valueOf(catId), catName)) {
				java.util.Map.Entry entry = (java.util.Map.Entry) iterator
						.next();
				catId = ((Integer) entry.getKey()).intValue();
				catName = (String) entry.getValue();
			}

		}
		return statesMap;
	}

	@RequestMapping(value = "/view/all", method = RequestMethod.GET)
	public String showCourses(Map model) throws TrainerCruiseServiceException {
		SessionUser userDetails = UserDetailsServiceImpl.currentUserDetails();
		long userId = userDetails.getUserId();
		List<GrantedAuthority> userRoles = collectionToList(userDetails.getAuthorities());
		GrantedAuthority gau = (GrantedAuthority) userRoles.get(0);
		String userType = gau.getAuthority();
		List<CourseSearchResultBean> resultsBeans = null;
		if (!userType.equalsIgnoreCase("trainee"))
			resultsBeans = courseScheduleService.getScheduledCourses(userId,
					new Date());
		CourseSearchResultPageBean bean = new CourseSearchResultPageBean();
		bean.setResultsBeans(resultsBeans);
		model.put("courseSearchResultPageBean", bean);
		return "courses";
	}

	public String showCourses(String viewType, Map model)
			throws TrainerCruiseServiceException {
		SessionUser userDetails = UserDetailsServiceImpl.currentUserDetails();
		long userId = userDetails.getUserId();
		List userRoles = collectionToList(userDetails.getAuthorities());
		GrantedAuthority gau = (GrantedAuthority) userRoles.get(0);
		String userType = gau.getAuthority();
		List resultsBeans = null;
		if (!userType.equalsIgnoreCase("trainee"))
			resultsBeans = courseScheduleService.getScheduledCourses(userId,
					new Date());
		CourseSearchResultPageBean bean = new CourseSearchResultPageBean();
		bean.setResultsBeans(resultsBeans);
		model.put("courseSearchResultPageBean", bean);
		return "courses";
	}

	@RequestMapping(value = "/new", method = RequestMethod.GET)
	public String showCreateCourseOverview(Map model)
			throws TrainerCruiseServiceException {
		CreateCourseOverviewForm courseForm = new CreateCourseOverviewForm();
		courseForm.setAction("saveCourseOverview");
		model.put("createCourseOverviewForm", courseForm);
		return "createCourseOverviewForm";
	}

	@RequestMapping(params = "action=saveCourseOverview", method = RequestMethod.POST)
	public String saveCourseOverview(CreateCourseOverviewForm overviewForm,
			BindingResult result, Map model)
			throws TrainerCruiseServiceException {
		SessionUser userDetails = UserDetailsServiceImpl.currentUserDetails();
		if (overviewForm.getOverview() != null
				&& overviewForm.getOverview().trim().equals("<br>"))
			overviewForm.setOverview("");
		if (overviewForm.getObjective() != null
				&& overviewForm.getObjective().equals("<br>"))
			overviewForm.setObjective("");
		if (overviewForm.getPreRequisite() != null
				&& overviewForm.getPreRequisite().equals("<br>"))
			overviewForm.setPreRequisite("");
		if (overviewForm.getAudience() != null
				&& overviewForm.getAudience().equals("<br>"))
			overviewForm.setAudience("");
		courseOverviewValidator.validate(overviewForm, result);
		System.out.println("Validation is DONEEEEEEEEEE");
		if (result.hasErrors())
			System.out.println((new StringBuilder("ERRORSSSSSSSSSSSSS "))
					.append(result.getErrorCount()).toString());
		CreateCourseAgendaForm agendaForm = new CreateCourseAgendaForm();
		CourseMaster courseMaster = new CourseMaster();
		courseMaster.setUserId(userDetails.getUserId());
		courseMaster.setAudience(overviewForm.getAudience());
		courseMaster.setCategory(overviewForm.getCategory());
		courseMaster.setCreatedTime(new Date());
		System.out.println((new StringBuilder("LEVELLLLLLLLLLLLLLLLLLL "))
				.append(overviewForm.getCourseLevel()).toString());
		courseMaster.setLevel(overviewForm.getCourseLevel());
		courseMaster.setObjective(overviewForm.getObjective());
		courseMaster.setOverview(overviewForm.getOverview());
		courseMaster.setPrerequisite(overviewForm.getPreRequisite());
		courseMaster.setTaggedSkills(overviewForm.getTaggedSkills());
		courseMaster.setTitle(overviewForm.getCourseTitle());
		courseMaster.setUpdatedTime(new Date());
		if (overviewForm.getCourseId() == 0L) {
			courseMasterService.saveCourseOverview(courseMaster);
			overviewForm.setCourseId(courseMaster.getCourseMasterId());
		} else {
			courseMaster.setCourseMasterId(overviewForm.getCourseId());
			courseMasterService.updateCourseOverview(courseMaster);
			courseMaster = courseMasterService.getCourseAgenda(
					courseMaster.getUserId(), courseMaster.getCourseMasterId());
			agendaForm.setAgenda(courseMaster.getAgenda());
			agendaForm.setTrainerDetails(courseMaster.getTrainerDetails());
			agendaForm.setNotes(courseMaster.getNotes());
		}
		agendaForm.setCourseId(overviewForm.getCourseId());
		agendaForm.setAction("saveCourseAgenda");
		model.put("createCourseAgendaForm", agendaForm);
		return "createCourseAgendaForm";
	}

	@RequestMapping(params = "action=saveCourseAgenda", method = RequestMethod.POST)
	public String saveCourseAgenda(CreateCourseAgendaForm agendaForm,
			BindingResult result, Map model)
			throws TrainerCruiseServiceException {
		SessionUser userDetails = UserDetailsServiceImpl.currentUserDetails();
		if (agendaForm.getAgenda() != null
				&& agendaForm.getAgenda().trim().equals("<br>"))
			agendaForm.setAgenda("");
		if (agendaForm.getTrainerDetails() != null
				&& agendaForm.getTrainerDetails().equals("<br>"))
			agendaForm.setTrainerDetails("");
		courseOverviewValidator.validateAgenda(agendaForm, result);
		if (result.hasErrors()) {
			return "createCourseAgendaForm";
		} else {
			CourseMaster courseMaster = new CourseMaster();
			courseMaster.setUserId(userDetails.getUserId());
			courseMaster.setAgenda(agendaForm.getAgenda());
			courseMaster.setTrainerDetails(agendaForm.getTrainerDetails());
			courseMaster.setNotes(agendaForm.getNotes());
			courseMaster.setCourseMasterId(agendaForm.getCourseId());
			courseMaster.setUpdatedTime(new Date());
			courseMasterService.updateCourseAgenda(courseMaster);
			CreateCourseScheduleForm scheduleForm = new CreateCourseScheduleForm();
			scheduleForm.setCourseId(agendaForm.getCourseId());
			scheduleForm.setTrainingType(1);
			scheduleForm.setAction("saveSchedule");
			model.put("createCourseScheduleForm", scheduleForm);
			return "createCourseScheduleForm";
		}
	}

	@RequestMapping(params = "action=saveSchedule", method = RequestMethod.POST)
	public String saveSchedule(CreateCourseScheduleForm scheduleForm,
			BindingResult result, Map model, HttpServletRequest req)
			throws TrainerCruiseServiceException, ParseException {
		SessionUser userDetails = UserDetailsServiceImpl.currentUserDetails();
		courseScheduleValidator.validate(scheduleForm, result);
		if (result.hasErrors())
			return "createCourseScheduleForm";
		CourseSchedule courseSchedule = new CourseSchedule();
		courseSchedule.setCourseMasterId(scheduleForm.getCourseId());
		courseSchedule.setCreatedTime(new Date());
		courseSchedule.setEndDate(ApplicationDateUtil.FORMATTER_WITHOUT_TIME
				.parse(scheduleForm.getEndDate()));
		courseSchedule.setEndTime(scheduleForm.getEndTime());
		courseSchedule.setFees(scheduleForm.getFees());
		courseSchedule.setLocationId(scheduleForm.getLocationId());
		courseSchedule.setStartDate(ApplicationDateUtil.FORMATTER_WITHOUT_TIME
				.parse(scheduleForm.getStDate()));
		courseSchedule.setStartTime(scheduleForm.getStTime());
		courseSchedule.setTotalSeats(scheduleForm.getTotalSeats());
		courseSchedule.setUpdatedTime(new Date());
		courseSchedule.setUserId(userDetails.getUserId());
		courseSchedule.setCourseType(scheduleForm.getTrainingType());
		courseScheduleService.saveSchedule(courseSchedule);
		String shortUrl = null;
		String fullUrl = null;
		TinyURLShortener shortener = new TinyURLShortener();
		try {
			String reqUrl = (new StringBuilder(String.valueOf(req.getScheme())))
					.append("//").append(req.getServerName()).append(":")
					.append(req.getServerPort()).append("/")
					.append(req.getContextPath()).append("/usr/course")
					.toString();
			shortUrl = shortener.getShortURL((new StringBuilder(String
					.valueOf(reqUrl))).append("/view/")
					.append(courseSchedule.getCourseScheduleId())
					.append("/details").toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (shortUrl != null)
			courseScheduleService.updateTinyUrl(userDetails.getUserId(),
					scheduleForm.getCourseId(),
					courseSchedule.getCourseScheduleId(), shortUrl);
		CreateCourseSocialForm socialForm = new CreateCourseSocialForm();
		socialForm.setTinyUrl(shortUrl);
		socialForm.setCourseScheduleId(courseSchedule.getCourseScheduleId());
		socialForm.setFullUrl(fullUrl);
		model.put("createCourseSocialForm", socialForm);
		return "courseSocial";
	}

	@RequestMapping(params = "action=viewCourseOverview", method = RequestMethod.POST)
	public String viewCourseOverview(CreateCourseAgendaForm agendaForm,
			Map model) throws TrainerCruiseServiceException {
		SessionUser userDetails = UserDetailsServiceImpl.currentUserDetails();
		long courseId = agendaForm.getCourseId();
		CourseMaster courseMaster = courseMasterService.getCourseOverview(
				userDetails.getUserId(), courseId);
		CreateCourseOverviewForm courseForm = new CreateCourseOverviewForm();
		courseForm.setAudience(courseMaster.getAudience());
		courseForm.setCategory(courseMaster.getCategory());
		courseForm.setCourseId(courseId);
		courseForm.setCourseLevel(courseMaster.getLevel());
		courseForm.setCourseTitle(courseMaster.getTitle());
		courseForm.setObjective(courseMaster.getObjective());
		courseForm.setOverview(courseMaster.getOverview());
		courseForm.setPreRequisite(courseMaster.getPrerequisite());
		courseForm.setTaggedSkills(courseMaster.getTaggedSkills());
		courseForm.setAction("saveCourseOverview");
		model.put("createCourseOverviewForm", courseForm);
		return "createCourseOverviewForm";
	}

	@RequestMapping(params = "action=viewCourseDetails", method = RequestMethod.POST)
	public String viewCourseDetails(String courseId, Map model)
			throws TrainerCruiseServiceException {
		CourseDetailsBean courseBean = new CourseDetailsBean();
		courseBean = courseScheduleService.getCourseDetails(Long
				.parseLong(courseId));
		System.out.println((new StringBuilder("COURSE BEANNNNNNNNNNNNNNNN "))
				.append(courseBean.getOverview()).toString());
		model.put("courseDetailsBean", courseBean);
		return "courseDetails";
	}

	@RequestMapping(value = "/req/new", method = RequestMethod.GET)
	public String viewRequestCourseForm(Map model)
			throws TrainerCruiseServiceException {
		CourseRequestForm reqForm = new CourseRequestForm();
		reqForm.setAction("saveRequest");
		model.put("courseRequestForm", reqForm);
		return "courseRequestForm";
	}

	@RequestMapping(params = "action=saveRequest", method = RequestMethod.POST)
	public String saveCourseRequest(CourseRequestForm reqForm,
			BindingResult result, Map model)
			throws TrainerCruiseServiceException {
		SessionUser userDetails = UserDetailsServiceImpl.currentUserDetails();
		if (reqForm.getExpecetdContents() != null
				&& reqForm.getExpecetdContents().trim().equals("<br>"))
			reqForm.setExpecetdContents("");
		courseRequestValidator.validate(reqForm, result);
		result.hasErrors();
		CourseRequests req = new CourseRequests();
		req.setAttendeesCount(reqForm.getAttendeesCount());
		req.setCategory(reqForm.getCategory());
		req.setCourseType(reqForm.getCourseType());
		req.setCreatedTime(new Date());
		req.setDuration(reqForm.getDuration());
		req.setExpectedContent(reqForm.getExpecetdContents());
		req.setExperienceRequired(reqForm.getExperienceRequired());
		req.setLevel(reqForm.getCourseLevel());
		req.setNotes(reqForm.getNotes());
		req.setSkillSets(reqForm.getSkillSets());
		req.setTitle(reqForm.getCourseTitle());
		req.setUserId(userDetails.getUserId());
		courseRequestService.saveCourseRequest(req);
		CourseRequestsLocation reqLoc = new CourseRequestsLocation();
		reqLoc.setRequestId(req.getRequestId());
		reqLoc.setAddress(reqForm.getAddress());
		reqLoc.setCity(reqForm.getCity());
		reqLoc.setState(reqForm.getState());
		reqLoc.setCreatedTime(new Date());
		reqLoc.setUpdatedTime(new Date());
		reqLoc.setZipCode(reqForm.getZipCode());
		courseReqLocService.saveLocation(reqLoc);
		return "courseRequestForm";
	}

	public List<GrantedAuthority> collectionToList(Collection<GrantedAuthority> collection) {
		List<GrantedAuthority> list;
		if (collection instanceof List)
			list = (List<GrantedAuthority>) collection;
		else
			list = new ArrayList<GrantedAuthority>(collection);
		return list;
	}

}
